The measurement and analysis of motor skills involves measurement of a set of movement profiles. In this project, 2 activities categorized as Gross-motor movements and 2 activities as Fine-motor movement were conducted. I used hand movement to measure fine motor.
A sensortile was placed on the wrist and foot of the subject for measurements of Fine and Gross motor movements respectively. The sensortile used are lightweight and does not affect the natural movement of the hands and legs.
Objective: Motor disorders are known in autism spectrum disorder (ASD). I collected motion profile of an autism subject and a control subject to evaluate the use of motion sensor for early detection of motor disorder/delays and monitoring of progress during therapy.
Methods: A sensortile was placed on the hand and wrist of the subjects. The sensortile holds an accelerometer that was used to collect the linear acceleration and a gyroscope used to collect the angular rate of the subject over a period of 60 seconds at a time.
The frequent association of ASD with other neurological and extra-neurological signs suggests that autism could be considered as a multiorgan systemic disorder with a primary central nervous system involvement.
Evidence of neuromuscular disorder (dystrophinopathies and congenital muscular dystrophy due to mutations of POMGnT1 gene) has been documented in a subset of patients affected by syndromic ASD, however, only few case reports and small samples studies with specific features have been reported in literature. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3235842/
It is the rate of change of the velocity of an object
It is the change in angular velocity about an axis. It is used to check the stability of the subject The unit of measurement is deg/sec
Measures the linear acceleration along X, Y, Z axes. It measures the acceleration of a body in its instantenous rest frame. The unit of measurement is m/s$^2$ or g (G-forces). The STEVAL-STLKT01V1 development kit was used for prototyping and evaluation. The sensortile holds a MEMS accelerometer that was used to collect the linear acceleration of the subject during an activity.
MEMS gyroscope was used to measure angular velocity. The units of angular velocity are measured in degrees per second (°/s) or revolutions per second (RPS). The angular rate is used to evaluate the balance of the subject since it senses rotation.

To upload firmware to the sensortile an external SWD debugger - ST-LINK/V2-1(STM32 Nucleo-64) development board was used.

Used to design prototypes/ firmware for the project
User interface for data collection and export
Four sets of activities were used to collect data. The activities are:
Two types of measurements were taken. The measurements are:
Two type of subjects were used in this analysis:


Further project description - https://youtu.be/O--TZ43lbMY
import glob
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#For Activity 1
path_1_autism = "Data logs/Activity_1_autism/*.csv"
path_1_control = "Data logs/Activity_1_control/*.csv"
#For Activity 2
path_2_autism = "Data logs/Activity_2_autism/*.csv"
path_2_control = "Data logs/Activity_2_control/*.csv"
#For Activity 3
path_3_autism = "Data logs/Activity_3_autism/*.csv"
path_3_control = "Data logs/Activity_3_control/*.csv"
#For Activity 4
path_4_autism = "Data logs/Activity_4_autism/*.csv"
path_4_control = "Data logs/Activity_4_control/*.csv"
#For Activity 1 - Hopping on one leg
path_activity_1_files_autism = np.array([])
path_activity_1_files_control = np.array([])
#For Activity 2 - Hopping on both legs
path_activity_2_files_autism = np.array([])
path_activity_2_files_control = np.array([])
#For Activity 3 - Color tiny dots
path_activity_3_files_autism = np.array([])
path_activity_3_files_control = np.array([])
#For Activity 4 - Stack small blocks
path_activity_4_files_autism = np.array([])
path_activity_4_files_control = np.array([])
# For activity 1 - Hopping on one leg
for fname_1_autism in glob.glob(path_1_autism):
path_activity_1_files_autism = np.append(path_activity_1_files_autism , fname_1_autism)
for fname_1_control in glob.glob(path_1_control):
path_activity_1_files_control= np.append(path_activity_1_files_control , fname_1_control)
# For activity 2 - Hopping on both legs
for fname_2_autism in glob.glob(path_2_autism):
path_activity_2_files_autism = np.append(path_activity_2_files_autism , fname_2_autism)
for fname_2_control in glob.glob(path_2_control):
path_activity_2_files_control= np.append(path_activity_2_files_control , fname_2_control)
# For activity 3 - Color tiny dots
for fname_3_autism in glob.glob(path_3_autism):
path_activity_3_files_autism = np.append(path_activity_3_files_autism , fname_3_autism)
for fname_3_control in glob.glob(path_3_control):
path_activity_3_files_control= np.append(path_activity_3_files_control , fname_3_control)
# For activity 4 - Stack small blocks
for fname_4_autism in glob.glob(path_4_autism):
path_activity_4_files_autism = np.append(path_activity_4_files_autism , fname_4_autism)
for fname_4_control in glob.glob(path_4_control):
path_activity_4_files_control= np.append(path_activity_4_files_control , fname_4_control)
#for j in path_activity_1_files_autism:
#data = pd.read_csv(j)
#fig1,ax1 = plt.subplots()
#ax1.set_title("Outlier detection")
#ax1.boxplot(data)
# For Activity 1
df_activity_1_autism = pd.read_csv(path_activity_1_files_autism[1])
df_activity_1_control = pd.read_csv(path_activity_1_files_control[1])
# For Activity 2
df_activity_2_autism = pd.read_csv(path_activity_2_files_autism[3])
df_activity_2_control = pd.read_csv(path_activity_2_files_control[3])
# For Activity 3
df_activity_3_autism = pd.read_csv(path_activity_3_files_autism[2])
df_activity_3_control = pd.read_csv(path_activity_3_files_control[2])
#For Activity 4
df_activity_4_autism = pd.read_csv(path_activity_4_files_autism[14])
df_activity_4_control = pd.read_csv(path_activity_4_files_control[14])
df_activity_3_control.head()
The data holds 7 columns. The time in milliseconds, the acceleration in 3 dimensional space (accX, accY, and accZ) and the angular rate in 3 dimensional space (Value 1, Value 2 and Value 3).
Let’s take a look at an axis with unevenly spaced datapoints.
accX = df_activity_3_control['accX[g]']/9.81
accY = df_activity_3_control['accY[g]']/9.81
accZ = df_activity_3_control['accZ[g]']/9.81
time = df_activity_3_control['time[ms]']
plt.figure(figsize=(24,16))
plt.plot(time, accX, "ro-")
plt.plot(time, accY, "bo-")
plt.plot(time, accZ, "go-")
#For the Angular rate
Value1= df_activity_3_control['Value 1']
Value2 = df_activity_3_control['Value 2']
Value3 = df_activity_3_control['Value 3']
time = df_activity_3_control['time[ms]']
plt.figure(figsize=(24,16))
plt.plot(time, Value1, "ro-")
plt.plot(time, Value2, "bo-")
plt.plot(time, Value3, "go-")
This is a high sample rate data. As we can see 1 second of data contains several datapoints. It might be beneficial to resample and select peaks from a Fast Fourier Transform. I will resample by downsampling
df_activity_3_control['accX[g]'] = df_activity_3_control['accX[g]']/9.81
df_activity_3_control['accY[g]']= df_activity_3_control['accY[g]']/9.81
df_activity_3_control['accZ[g]'] = df_activity_3_control['accZ[g]']/9.81
df_activity_3_control['Timedelta'] = pd.to_timedelta(df_activity_3_control['time[ms]'],'ms')
df_activity_3_control.head()
df_activity_3_control = df_activity_3_control.set_index(df_activity_3_control['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df_activity_3_control
X = df_activity_3_control['accX[g]']/9.81
Y = df_activity_3_control['accY[g]']/9.81
Z = df_activity_3_control['accZ[g]']/9.81
time = df_activity_3_control['time[ms]']
plt.figure(figsize=(24,16))
plt.figure(figsize=(24,16))
plt.plot(time, X, "ro-")
plt.plot(time, Y, "bo-")
plt.plot(time, Z, "go-")
X = df_activity_3_control['Value 1']
Y = df_activity_3_control['Value 2']
Z = df_activity_3_control['Value 3']
time = df_activity_3_control['time[ms]']
plt.figure(figsize=(24,16))
plt.figure(figsize=(24,16))
plt.plot(time, X, "ro-")
plt.plot(time, Y, "bo-")
plt.plot(time, Z, "go-")
# Filter requirements.
from scipy.signal import butter,filtfilt
# Sample period = 60secs
T = 60
# sample frequency 1 sample per sec
fs = 1
# desired cutoff frequency of the filter, Hz , slightly higher than actual 0.017 Hz,
#Signal Freq = 1 signal / 60 sec = 0.017 Hz
cutoff = 0.20
nyq = 0.5 * fs
#polynomial order of the frequency
order = 2
#Total number of samples
n = int(T * fs)
def butter_lowpass_filter(data, cutoff, fs, order):
normal_cutoff = cutoff / nyq
# Get the filter coefficients
b, a = butter(order, normal_cutoff, btype='low', analog=False)
y = filtfilt(b, a, data)
return y
import plotly.graph_objects as go
filteredx = butter_lowpass_filter(df_activity_3_control['Value 1'], cutoff, fs, order)
filteredy = butter_lowpass_filter(df_activity_3_control['Value 2'], cutoff, fs, order)
filteredz = butter_lowpass_filter(df_activity_3_control['Value 3'], cutoff, fs, order)
fig = go.Figure()
fig.add_trace(go.Scatter(
y = df_activity_3_control['Value 1'],
line = dict(shape = 'spline' ),
name = 'Angular Rate X with noise'
))
fig.add_trace(go.Scatter(
y = filteredx,
line = dict(shape = 'spline' ),
name = 'filtered signal'
))
fig.show()
fig = go.Figure()
fig.add_trace(go.Scatter(
y = df_activity_3_control['Value 2'],
line = dict(shape = 'spline' ),
name = 'Angular Rate Y with noise'
))
fig.add_trace(go.Scatter(
y = filteredy,
line = dict(shape = 'spline' ),
name = 'filtered signal'
))
fig.show()
fig = go.Figure()
fig.add_trace(go.Scatter(
y = df_activity_3_control['Value 3'],
line = dict(shape = 'spline' ),
name = 'Angular Rate Z with noise'
))
fig.add_trace(go.Scatter(
y = filteredz,
line = dict(shape = 'spline' ),
name = 'filtered signal'
))
fig.show()
df_average = pd.DataFrame()
for i in path_activity_1_files_autism:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Value 1'] = df['Value 1']/9.81
df['Value 2']= df['Value 2']/9.81
df['Value 3'] = df['Value 3']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d = {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average= pd.concat([df_average,e], axis=1)
df_activity_1_autism=df_average.dropna(axis=1, how="any")
# I will now plot the Activity 1
df_activity_1_autism_transpose = df_activity_1_autism.T
df_activity_1_autism_transpose.reset_index(drop=True, inplace=True)
#df_activity_1_autism_transpose.drop(['measurements'], axis=1)
df_activity_1_autism_transpose['activity'] = "Activity 1"
df_activity_1_autism_transpose['Category'] = "Autism"
df_activity_1_autism_transpose
df_average_2_autism = pd.DataFrame()
for i in path_activity_2_files_autism:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d_control = {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e_control = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average_2_autism = pd.concat([df_average_2_autism ,e], axis=1)
df_activity_2_autism=df_average_2_autism.dropna(axis=1, how="any")
df_activity_2_autism_transpose =df_activity_2_autism.T
df_activity_2_autism_transpose.reset_index(drop=True, inplace=True)
df_activity_2_autism_transpose['activity'] = "Activity 2"
df_activity_2_autism_transpose['Category'] = "Autism"
df_activity_2_autism_transpose
df_average_3_autism = pd.DataFrame()
for i in path_activity_3_files_autism:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d = {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average_3_autism = pd.concat([df_average_3_autism ,e], axis=1)
df_activity_3_autism=df_average_3_autism.dropna(axis=1, how="any")
df_activity_3_autism_transpose =df_activity_3_autism.T
df_activity_3_autism_transpose.reset_index(drop=True, inplace=True)
df_activity_3_autism_transpose['activity'] = "Activity 3"
df_activity_3_autism_transpose['Category'] = "Autism"
df_activity_3_autism_transpose
df_average_4_autism = pd.DataFrame()
for i in path_activity_4_files_autism:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d = {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average_4_autism = pd.concat([df_average_4_autism ,e], axis=1)
df_activity_4_autism=df_average_4_autism.dropna(axis=1, how="any")
df_activity_4_autism_transpose =df_activity_4_autism.T
df_activity_4_autism_transpose.reset_index(drop=True, inplace=True)
df_activity_4_autism_transpose['activity'] = "Activity 4"
df_activity_4_autism_transpose['Category'] = "Autism"
df_activity_4_autism_transpose
df_average_1_control = pd.DataFrame()
for i in path_activity_1_files_control:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d= {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average_1_control = pd.concat([df_average_1_control ,e], axis=1)
df_activity_1_control=df_average_1_control.dropna(axis=1, how="any")
df_activity_1_control_transpose = df_activity_1_control.T
df_activity_1_control_transpose.reset_index(drop=True, inplace=True)
df_activity_1_control_transpose['activity'] = "Activity 1"
df_activity_1_control_transpose['Category'] = "Control"
df_activity_1_control_transpose
df_average_2_control = pd.DataFrame()
for i in path_activity_2_files_control:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d= {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average_2_control = pd.concat([df_average_2_control ,e], axis=1)
df_activity_2_control=df_average_2_control.dropna(axis=1, how="any")
df_activity_2_control_transpose = df_activity_2_control.T
df_activity_2_control_transpose.reset_index(drop=True, inplace=True)
df_activity_2_control_transpose['activity'] = "Activity 2"
df_activity_2_control_transpose['Category'] = "Control"
df_activity_2_control_transpose
df_average_3_control = pd.DataFrame()
for i in path_activity_3_files_control:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d= {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average_3_control = pd.concat([df_average_3_control ,e], axis=1)
df_activity_3_control=df_average_3_control.dropna(axis=1, how="any")
df_activity_3_control_transpose = df_activity_3_control.T
df_activity_3_control_transpose.reset_index(drop=True, inplace=True)
df_activity_3_control_transpose['activity'] = "Activity 3"
df_activity_3_control_transpose['Category'] = "Control"
df_activity_3_control_transpose
df_average_4_control = pd.DataFrame()
for i in path_activity_1_files_control:
df = pd.read_csv(i)
df['accX[g]'] = df['accX[g]']/9.81
df['accY[g]']= df['accY[g]']/9.81
df['accZ[g]'] = df['accZ[g]']/9.81
df['Timedelta'] = pd.to_timedelta(df['time[ms]'],'ms')
df = df.set_index(df['Timedelta'])[['time[ms]','accX[g]','accY[g]', 'accZ[g]', 'Value 1', 'Value 2', 'Value 3']].resample('1s').mean()
df['accX[g]'] = butter_lowpass_filter(df['accX[g]'], cutoff, fs, order)
df['accY[g]'] = butter_lowpass_filter(df['accY[g]'], cutoff, fs, order)
df['accZ[g]'] = butter_lowpass_filter(df['accZ[g]'], cutoff, fs, order)
df['Value 1'] = butter_lowpass_filter(df['Value 1'], cutoff, fs, order)
df['Value 2'] = butter_lowpass_filter(df['Value 2'], cutoff, fs, order)
df['Value 3'] = butter_lowpass_filter(df['Value 3'], cutoff, fs, order)
d= {'measurements': ['time', 'accx', 'accy', 'accz', 'value 1', 'value 2', 'value 3'],'Column 1': [df['time[ms]'].mean(), df['accX[g]'].mean(), df['accY[g]'].mean(), df['accZ[g]'].mean(), df['Value 1'].mean(), df['Value 2'].mean(), df['Value 3'].mean()]}
e = pd.DataFrame(d).set_index('measurements').rename_axis('columns', axis=1)
df_average_4_control = pd.concat([df_average_4_control ,e], axis=1)
df_activity_4_control=df_average_4_control.dropna(axis=1, how="any")
df_activity_4_control_transpose = df_activity_4_control.T
df_activity_4_control_transpose.reset_index(drop=True, inplace=True)
df_activity_4_control_transpose['activity'] = "Activity 4"
df_activity_4_control_transpose['Category'] = "Control"
df_activity_4_control_transpose
frames = [df_activity_1_control_transpose, df_activity_1_autism_transpose, df_activity_2_control_transpose, df_activity_2_autism_transpose, df_activity_3_control_transpose, df_activity_3_autism_transpose,df_activity_4_control_transpose, df_activity_4_autism_transpose]
result = pd.concat(frames)
result
import seaborn as sns
%matplotlib inline
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
import statsmodels.api as sm #Linear Regression
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import log_loss, accuracy_score
from keras.callbacks import EarlyStopping, ModelCheckpoint
import keras
from keras.models import Sequential # intitialize the ANN
from keras.layers import Dense, Dropout # create layers
from sklearn.ensemble import BaggingClassifier
categorical = ['activity', 'Category']
lbl = preprocessing.LabelEncoder()
for col in categorical:
result[col] = lbl.fit_transform(result[col].astype(str))
print(result[['activity','Category']])
Divide the dataset into X_train, y_train, X_test, y_test, ratio 80:20, random_state = 109, stratify on Category.
Check the ratio for y_train and y_test
X_train, X_test, y_train, y_test = train_test_split(result.loc[:, result.columns != 'Category'], result.Category, test_size=0.2, random_state=109, stratify=result.Category)
y_train.value_counts(normalize=True), y_test.value_counts(normalize=True)
X_train.shape
X_test.shape
Linear Regression - Ordinary Least Squares
model = sm.OLS(y_train, X_train).fit()
print_model = model.summary()
linear_reg_log_loss = log_loss(y_test, model.predict(X_test))
print(linear_reg_log_loss)
print(accuracy_score(y_test, model.predict(X_test)>0.5), accuracy_score(y_test,np.zeros(y_test.shape)))
Logistic Regression
model = LogisticRegression(C=10000, random_state=109, max_iter=1000, solver='liblinear')
model.fit(X_train,y_train)
preds = model.predict_proba(X_test)
logistic_reg_log_loss = log_loss(y_test, preds[:,1])
print(logistic_reg_log_loss)
print(accuracy_score(y_test, preds[:,1]>0.5), accuracy_score(y_test,np.zeros(y_test.shape)))
Logistic Regression ---Scaled
scaler = StandardScaler().fit(X_train.astype(np.float64))
train_scaled = scaler.transform(X_train.astype(np.float64))
test_scaled = scaler.transform(X_test.astype(np.float64))
model = LogisticRegression(C=0.11, random_state=109,penalty='l2' ,max_iter=1000, solver='liblinear')
model.fit(train_scaled,y_train)
preds = model.predict_proba(test_scaled)
reg_log_loss = log_loss(y_test, preds[:,1])
print(reg_log_loss)
Bagging Classifier
model = BaggingClassifier(random_state=109, n_estimators=100)
model.fit(X_train, y_train)
preds = model.predict_proba(X_test)
bagging_log_loss = log_loss(y_test, preds[:,1])
print(bagging_log_loss)
Random Forest
model = RandomForestClassifier(n_estimators = 500, random_state = 109)
model.fit(X_train,y_train)
preds = model.predict_proba(X_test)
rf_log_loss = log_loss(y_test, preds[:,1])
print(rf_log_loss)
Neural Network
# Initializing the NN
model = Sequential()
# layers
model.add(Dense(units = 40, kernel_initializer = 'glorot_uniform', activation = 'relu', input_dim = 8))
model.add(Dense(units = 30, kernel_initializer = 'glorot_uniform', activation = 'relu'))
model.add(Dense(units = 25, kernel_initializer = 'glorot_uniform', activation = 'relu'))
model.add(Dense(units = 20, kernel_initializer = 'glorot_uniform', activation = 'relu'))
model.add(Dense(units = 15, kernel_initializer = 'glorot_uniform', activation = 'relu'))
model.add(Dense(units = 10, kernel_initializer = 'glorot_uniform', activation = 'relu'))
model.add(Dense(units = 5, kernel_initializer = 'glorot_uniform', activation = 'relu'))
model.add(Dropout(0.2))
model.add(Dense(units = 1, kernel_initializer = 'glorot_uniform', activation = 'sigmoid'))
print(model.summary())
# Compiling the ANN
model.compile(optimizer = 'Nadam',
loss = 'binary_crossentropy' ,
metrics = ['accuracy'])
# Set callback functions to early stop training and save the best model so far
callbacks = [EarlyStopping(monitor='val_loss', patience=4),
ModelCheckpoint(filepath='best_model.h5', monitor='val_loss', save_best_only=True)]
# Train the ANN
history = model.fit(train_scaled, y_train, batch_size = 256, epochs = 50,
callbacks=callbacks, # Early stopping
validation_data = (test_scaled, y_test))
nn_log_loss = model.evaluate(test_scaled, y_test)[0]
print(nn_log_loss)
data = {'Model':['Linear Regression', 'Logistic Regression', 'Regularized Logistic regression', 'Bagged decision tree', 'Random Forest', 'NN Model'],
'Logloss':[linear_reg_log_loss , logistic_reg_log_loss, reg_log_loss, bagging_log_loss, rf_log_loss, nn_log_loss]}
pd.DataFrame(data).sort_values('Logloss')
Logarithmic loss measures the performance of a classification model where the prediction input is a probability value between 0 and 1. The goal of our machine learning models is to minimize this value. A perfect model would have a log loss of 0. The Bagging classifier performed best in this model.
from sklearn import model_selection
model = BaggingClassifier(random_state=109, n_estimators=100)
model.fit(X_train, y_train)
preds = model.predict_proba(X_test)
bagging_log_loss = log_loss(y_test, preds[:,1])
print(bagging_log_loss)
seed = 7
kfold = model_selection.KFold(n_splits=5, random_state=seed)
results = model_selection.cross_val_score(model, X_train, y_train, cv=kfold)
print(results.mean())
To improve the accuracy of the bagging classifier, I applied a 5 fold CV. Which resulted in a robust estimate of model accuracy.
Given the successful performance of the Bagging classifier and the neural network in this experiment more sample size and subjects will be needed to come to a definite conclusion on the use of motion sensors in convienent ways that will lead to discoveries that are difficult to evaluate by humans. Other classifiers as it relates to the types of activities and the category of motor with delays can also be build using the data collected.